﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using NetDon.OA.Data.CollectionClasses;
using NetDon.OA.Data.DaoClasses;
using NetDon.OA.Data.EntityClasses;
using NetDon.OA.Data.HelperClasses;
using NetDon.OA.Data.Linq;
using NetDon.OA.Interface;
using NetDon.OA.Interface.Admin;
using NetDon.Utilities;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace NetDon.OA.Business.Admin
{
    public class UserService : IUserService
    {
        #region Implementation of IUserService
        public bool GetUser(string userName, string nickName)
        {
            var meta = new LinqMetaData();
            var list = (from applicationUser in meta.User
                        where applicationUser.UserName == userName || applicationUser.NickName == nickName
                        select applicationUser).ToList();
            return list.Count > 0 ? true : false;
        }
        public bool AddUser(UserData userData)
        {
            var trans = new Transaction(IsolationLevel.ReadCommitted, "AddUser");
            //check if the user exists
            var meta = new LinqMetaData();
            var list = (from applicationUser in meta.User
                        where applicationUser.UserName == userData.UserName
                        select applicationUser).ToList();
            if (list.Count > 0)
            {
                userData.SetError("DuplicateUser", "用户名已经存在！");
                return false;
            }

            if (!string.IsNullOrWhiteSpace(userData.NickName))
            {

                list = (from applicationUser in meta.User
                        where applicationUser.NickName == userData.NickName
                        select applicationUser).ToList();
                if (list.Count > 0)
                {
                    userData.SetError("DuplicateUser", "用户别名已经存在！");
                    return false;
                }
            }

            try
            {
                var objUser = new UserEntity
                {
                    UserId = Guid.NewGuid(),
                    Email = userData.Email,
                    Gender = (int)userData.Gender,
                    Password = MiscUtilities.ComputePasswordHash(userData.Password),
                    FullName = userData.FullName,
                    CompanyId = userData.CompanyId,
                    UserName = userData.UserName,
                    Address = userData.Address,
                    Mobile = userData.Mobile,
                    //Phone = userData.Phone,
                    DepartId = userData.DepartId,
                    PositionId = userData.PositionId,
     NickName = userData.NickName,
                    CreateDate = userData.CreateDate,
                    Birthday = userData.Birthday,
                    Type = (int)userData.Type,
                    UserStatus = (int)userData.UserStatus
                };
                trans.Add(objUser);
                objUser.Save();

                var userRole = new UserRoleEntity
                {
                    UserId = objUser.UserId,
                    RoleId = userData.RoleId
                };
                trans.Add(userRole);
                userRole.Save();

              

                trans.Commit();
                return true;
            }
            catch (Exception)
            {
                trans.Rollback();
                throw;
            }
        }

        public UserData GetUser(Guid userId)
        {
            var meta = new LinqMetaData();
            var list = (from applicationUser in meta.User
                        where applicationUser.UserId == userId
                        select applicationUser).ToList();
            return GetUserDataFromUserEntity(list.FirstOrDefault());
        }

        public UserData GetUserByLoginName(string strLoginName)
        {
            var meta = new LinqMetaData();
            var list = (from applicationUser in meta.User
                        where applicationUser.UserName == strLoginName
                        select applicationUser).ToList();
            return GetUserDataFromUserEntity(list.FirstOrDefault());
        }

        public int GetUserCount(UserSearchCriteria criteria)
        {
            var collection = new UserCollection();
            return collection.GetDbCount(GetUserSearchPredicate(criteria));
        }

        private IPredicate GetUserSearchPredicate(UserSearchCriteria criteria)
        {
            var predicate = new PredicateExpression();
            var loginNameExpression = new PredicateExpression();
            if (!string.IsNullOrEmpty(criteria.UserName))
            {
                loginNameExpression |= UserFields.UserName % ("%" + criteria.UserName + "%");
                loginNameExpression |= UserFields.NickName % ("%" + criteria.UserName + "%");
                predicate &= loginNameExpression;
            }

            if (!string.IsNullOrEmpty(criteria.Password))
            {
                predicate &= UserFields.Password == criteria.Password;
            }

            if (criteria.CompanyId.HasValue && criteria.CompanyId != Guid.Empty)
            {
                predicate &= UserFields.CompanyId == criteria.CompanyId.Value;
            }

            if (criteria.DepartId.HasValue && criteria.DepartId != Guid.Empty)
            {
                predicate &= UserFields.DepartId == criteria.DepartId.Value;
            }

            if (criteria.PositionId.HasValue && criteria.PositionId != Guid.Empty)
            {
                predicate &= UserFields.PositionId == criteria.PositionId.Value;
            }

            if (!string.IsNullOrEmpty(criteria.Email))
            {
                predicate &= UserFields.Email % ("%" + criteria.Email + "%");
            }

            if (!string.IsNullOrEmpty(criteria.FullName))
            {
                predicate &= UserFields.FullName % ("%" + criteria.FullName + "%");
            }

            if (criteria.UserType.HasValue)
            {
                switch (criteria.UserType.Value)
                {
                    case UserType.StoreUser:
                        predicate &= UserFields.Type == (int)UserType.StoreUser;
                        break;
                    //case UserType.Administrators:
                    //    predicate &= UserFields.Type == (int)UserType.Administrators;
                    //    break;
                    case UserType.InternalUser:
                        predicate &= UserFields.Type == (int)UserType.InternalUser;
                        break;
                }
            }

            if (criteria.Status.HasValue)
            {
                switch (criteria.Status.Value)
                {
                    case UserStatus.Active:
                        predicate &= UserFields.UserStatus == (int)UserStatus.Active;
                        break;
                    case UserStatus.NotActive:
                        predicate &= UserFields.UserStatus == (int)UserStatus.NotActive;
                        break;
                }
            }
            return predicate;
        }

        public DataTable SearchUsers(UserSearchCriteria criteria, string sortExpression, SortDirection sortDirection, int pageSize, int pageIndex)
        {
            var fields = new EntityFields(14);
            var index = 0;
            fields[index++] = UserFields.UserName;
            fields[index++] = UserFields.FullName;
            fields[index++] = UserFields.Email;
            fields[index++] = UserFields.Type;
            fields[index++] = UserFields.UserStatus;
            fields[index++] = UserFields.Phone;
            fields[index++] = UserFields.UserId;
            fields[index++] = UserFields.CreateDate;
            fields[index++] = UserFields.NickName;
            fields[index++] = UserFields.Gender;
            fields[index++] = UserFields.PositionId;
            fields[index++] = PostFields.PostName;
            fields[index++] = DepartmentFields.DepartId;
            fields[index++] = DepartmentFields.DepartName;

            var sort = GetSortExpression(sortExpression, sortDirection);
            var table = new DataTable();
            var dao = new TypedListDAO();
            dao.GetMultiAsDataTable(fields, table, 0, sort, GetUserSearchPredicate(criteria), GetUserSearchRelations(criteria), false,
                        null, null, pageIndex + 1, pageSize);
            return table;
        }

        public List<UserData> SearchUsersByCondition(UserSearchCriteria criteria, string sortExpression, System.Web.UI.WebControls.SortDirection sortDirection, int pageSize, int pageIndex)
        {
            var relation = new RelationCollection();
            var sort = GetSortExpression(sortExpression, sortDirection);
            var collection = new UserCollection();
            collection.GetMulti(GetUserSearchPredicate(criteria), 0, sort, relation, pageIndex + 1, pageSize);
            var listReturn = new List<UserData>();
            foreach (var userEntity in collection)
            {
                listReturn.Add(GetUserDataFromUserEntity(userEntity));
            }

            return listReturn;
        }
        private IRelationCollection GetUserSearchRelations(UserSearchCriteria criteria)
        {
            var relations = new RelationCollection()
                                {

                                };
            relations.Add(UserEntity.Relations.PostEntityUsingPositionId, JoinHint.Left);
            relations.Add(UserEntity.Relations.DepartmentEntityUsingDepartId, JoinHint.Left);
            return relations;
        }
        public string GetUserEmail(Guid userId)
        {
            var user = new UserEntity(userId);
            return user.Email;
        }

        public UserData GetUserByLoginName(string strLoginName, string strNickName)
        {
            var meta = new LinqMetaData();
            var list = (from applicationUser in meta.User
                        where applicationUser.UserName == strLoginName || applicationUser.NickName == strNickName
                        select applicationUser).ToList();
            return GetUserDataFromUserEntity(list.FirstOrDefault());
        }

        public bool ChangeStatus(Guid userId, UserStatus status)
        {
            var trans = new Transaction(IsolationLevel.ReadCommitted, "Change user status");
            try
            {
                var user = new UserEntity(userId);
                user.UserStatus = (int)status;
                user.Save();
                trans.Commit();
                return true;
            }
            catch (Exception)
            {
                trans.Rollback();
                throw;
            }
        }

        public bool ModifyUser(UserData userData)
        {
            var transaction = new Transaction(IsolationLevel.ReadCommitted, "ModifyUser");
            try
            {
                var objUser = new UserEntity(userData.UserId);
                objUser.Email = userData.Email;
                objUser.Gender = (int)userData.Gender;
                //Password = MiscUtilities.ComputePasswordHash(userData.Password),// not provide interface here for change password
                objUser.FullName = userData.FullName;
                objUser.CompanyId = userData.CompanyId;
                objUser.UserName = userData.UserName;
                objUser.Address = userData.Address;
                objUser.Mobile = userData.Mobile;
                //Phone = userData.Phone;
                objUser.DepartId = userData.DepartId;
                objUser.PositionId = userData.PositionId;
 objUser.NickName = userData.NickName;
                objUser.CreateDate = userData.CreateDate;
                objUser.Birthday = userData.Birthday;
                objUser.Type = (int)userData.Type;
                objUser.UserStatus = (int)userData.UserStatus;
                objUser.EmailPassword = userData.EmailPassword;
                objUser.Remarks = userData.Remarks;
                transaction.Add(objUser);
                objUser.Save();

                //Delete the user role relactionship
                var userRoleCollection = new UserRoleCollection();
                transaction.Add(userRoleCollection);
                userRoleCollection.DeleteMulti(UserRoleFields.UserId == userData.UserId);

                //Add a new relactionship
                var userRole = new UserRoleEntity
                {
                    UserId = objUser.UserId,
                    RoleId = userData.RoleId
                };
                transaction.Add(userRole);
                userRole.Save();

              

                transaction.Commit();
                return true;
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }
        }

      

        /// <summary>
        /// Get users for viewing calendar
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        //public List<UserData> GetCalendarUsers(Guid userId)
        //{
        //    var metaData = new LinqMetaData();

        //    var currentUser = (from user in metaData.User
        //                       where user.UserId == userId
        //                       select user).FirstOrDefault();
        //    IList<UserEntity> usersTemp = null;
        //    if (currentUser.DepartId != null)
        //    {
        //        usersTemp = (from entity in metaData.User
        //                     where entity.DepartId == currentUser.DepartId
        //                     && entity.UserStatus == (int)UserStatus.Active
        //                     select entity).ToList();
        //    }
        //    else if (currentUser.CompanyId != null)
        //    {
        //        usersTemp = (from entity in metaData.User
        //                     where entity.CompanyId == currentUser.CompanyId
        //                     && entity.UserStatus == (int)UserStatus.Active
        //                     select entity).ToList();
        //    }
        //    else
        //    {
        //        usersTemp = (from entity in metaData.User
        //                     where entity.UserStatus == (int)UserStatus.Active
        //                     select entity).ToList();
        //    }
        //    var users = new List<UserEntity>();

        //    foreach (var userEntity in usersTemp)
        //    {
        //        if (HasPermission(currentUser, userEntity))
        //        {
        //            users.Add(userEntity);
        //        }
        //    }



        //    if (users.Count > 0)
        //    {
        //        var list = new List<UserData>();
        //        foreach (var userEntity in users)
        //        {

        //            var entity = userEntity;
        //            var temp = list.Where(u => u.UserId == entity.UserId).FirstOrDefault();
        //            if (temp == null)
        //            {
        //                var data = GetUserDataFromUserEntity(userEntity);
        //                list.Add(data);
        //            }

        //        }
        //        return list;
        //    }
        //    return null;
        //}

        //private bool HasPermission(UserEntity currentUser, UserEntity entityUser)
        //{
        //    if (currentUser.DepartId != null && entityUser.DepartId != null)
        //    {
        //        if (currentUser.DepartId == entityUser.DepartId)
        //        {
        //            return ComparePostLevel(currentUser, entityUser);
        //        }
        //        return false;
        //    }
        //    if (currentUser.CompanyId != null && currentUser.DepartId == null)
        //    {

        //        if (currentUser.CompanyId == entityUser.CompanyId)
        //        {
        //            return ComparePostLevel(currentUser, entityUser);
        //        }
        //        return false;
        //    }

        //    return false;
        //}
        ////use for templete filter the permission user
        //public bool HasPermission(Guid currentUserId, Guid entityUserId)
        //{
        //    var meta = new LinqMetaData();
        //    var currentUser = meta.User.Where(u => u.UserId == currentUserId).FirstOrDefault();
        //    var entityUser = meta.User.Where(u => u.UserId == entityUserId).FirstOrDefault();
        //    if (currentUser.DepartId != null && entityUser.DepartId != null)
        //    {
        //        if (currentUser.DepartId == entityUser.DepartId)
        //        {
        //            return ComparePostLevel(currentUser, entityUser);
        //        }
        //        return false;
        //    }
        //    if (currentUser.CompanyId != null && currentUser.DepartId == null)
        //    {

        //        if (currentUser.CompanyId == entityUser.CompanyId)
        //        {
        //            return ComparePostLevel(currentUser, entityUser);
        //        }
        //        return false;
        //    }

        //    return false;
        //}

        //private bool ComparePostLevel(UserEntity currentUser, UserEntity entityUser)
        //{
        //    var meta = new LinqMetaData();
        //    var currentPost = meta.Post.Where(p => p.PostId == currentUser.PositionId).FirstOrDefault();
        //    var entityPost = meta.Post.Where(p => p.PostId == entityUser.PositionId).FirstOrDefault();
        //    if (currentPost != null && entityPost != null)
        //    {
        //        var current = meta.Dictionary.Where(d => d.Oid == currentPost.PostLevel).FirstOrDefault();

        //        var entity = meta.Dictionary.Where(d => d.Oid == entityPost.PostLevel).FirstOrDefault();

        //        if (current != null && entity != null)
        //        {
        //            int currentPostLevel = 0; int viewerPostLevel = 0;
        //            int.TryParse(current.FieldValue, out  currentPostLevel);
        //            int.TryParse(entity.FieldValue, out  viewerPostLevel);
        //            return currentPostLevel >= viewerPostLevel;
        //        }
        //    }
        //    return false;
        //}

 
        #endregion

        #region Private provider

        private SortExpression GetSortExpression(string strInput, SortDirection sortDirection)
        {
            SortExpression sort;
            switch (strInput)
            {
                case "UserName":
                    sort = new SortExpression(UserFields.UserName | (SortOperator)(int)sortDirection);
                    break;
                case "FullName":
                    sort = new SortExpression(UserFields.FullName | (SortOperator)(int)sortDirection);
                    break;
                case "Email":
                    sort = new SortExpression(UserFields.Email | (SortOperator)(int)sortDirection);
                    break;
                case "Type":
                    sort = new SortExpression(UserFields.Type | (SortOperator)(int)sortDirection);
                    break;
                case "Status":
                    sort = new SortExpression(UserFields.UserStatus | (SortOperator)(int)sortDirection);
                    break;
                case "CreateDate":
                    sort = new SortExpression(UserFields.CreateDate | (SortOperator)(int)sortDirection);
                    break;
                case "NickName":
                    sort = new SortExpression(UserFields.NickName | (SortOperator)(int)sortDirection);
                    break;
                default:
                    sort = new SortExpression
                    {
                        UserFields.UserName | SortOperator.Ascending,
                        UserFields.NickName | SortOperator.Ascending
                    };
                    break;

            }
            return sort;
        }

        private void RemoveUser(ITransaction transaction, Guid userId)
        {
            var userCollection = new UserCollection();
            transaction.Add(userCollection);
            userCollection.DeleteMulti(UserFields.UserId == userId);
        }

        private UserData GetUserDataFromUserEntity(UserEntity entity)
        {
            //modify by joe
            if (entity == null || entity.IsNew)
            {
                return null;
            }
            GenderType gt = GenderType.UnKnown;
            if (entity.Gender.HasValue)
            {
                gt = EnumUtilities.Parse<GenderType>(entity.Gender.Value.ToString());
            }
            var meta = new LinqMetaData();
            var roleEntity = (from role in meta.UserRole
                              where role.UserId == entity.UserId
                              select role).FirstOrDefault();

            var applicationUserData = new UserData()
            {
                UserId = entity.UserId,
                IsNew = false,
                Type = (UserType)entity.Type,
                FullName = entity.FullName,
                Email = entity.Email,
                Gender = gt,
                Password = entity.Password,
                UserStatus = (UserStatus)entity.UserStatus,
                CompanyId = entity.CompanyId,
                DepartId = entity.DepartId,
                UserName = entity.UserName,
                Address = entity.Address,
                Mobile = entity.Mobile,
                Phone = entity.Phone,
                PositionId = entity.PositionId,
                PostName = entity.PositionId.HasValue ? ServiceContainer.GetService<IPostService>().GetPostName((Guid)entity.PositionId) : string.Empty,
                NickName = entity.NickName,
                CreateDate = entity.CreateDate,
                Birthday = entity.Birthday,
                EmailPassword = entity.EmailPassword,
                Remarks = entity.Remarks
            };
            if (roleEntity != null)
            {
                applicationUserData.RoleId = roleEntity.RoleId;
            }

            return applicationUserData;
        }
        public bool ValidateUserReferenced(Guid userId)
        {
            return false;
        }

        public void RemoveUser(Guid userId)
        {
            var transaction = new Transaction(IsolationLevel.ReadCommitted, "Delete User");
            try
            {
            
                RemoveUser(transaction, userId);
                transaction.Commit();
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }
        }
        #endregion
    }
}